﻿
/*=========================================
* Author: VIP
* Description: 对ScrollRect的优化 增加滑动结束回调、搜索定位
==========================================*/

using DG.Tweening;
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;

enum VIPPosition{
    UP,
    CENTER,
    DOWN
}

//[AddComponentMenu("UI/VIPScrollRect")]
public class VIPScrollRect : ScrollRect{

    /// <summary>
    /// 限制惯性持续时间
    /// </summary>
    private float inertiaMaxTime = 0.5f;

    private float scrolledTime = 0f;
    private UnityAction<GameObject> slideComplete = null;

    public override void OnEndDrag(PointerEventData eventData)
    {
        base.OnEndDrag(eventData);
        scrolledTime = 0f;
    }

    public override void OnDrag(PointerEventData eventData)
    {
        base.OnDrag(eventData);
        scrolledTime = 0f;
    }

    public override void StopMovement()
    {
        base.StopMovement();
    }

    //private Vector2 _prePos = new Vector2(float.MaxValue, float.MaxValue);

    protected override void LateUpdate()
    {
        // base.LateUpdate();
    }

    private void Update()
    {
        base.LateUpdate();
    }

    protected override void SetContentAnchoredPosition(Vector2 position)
    {
        if (scrolledTime >= inertiaMaxTime)
        {
            if (slideComplete != null)
            {
                slideComplete(transform.gameObject);
                slideComplete = null;
            }
            return;
        }

        base.SetContentAnchoredPosition(position);

        scrolledTime += Time.unscaledDeltaTime;
    }

    private VIPScrollRect scrollRect;

    protected override void Start()
    {
        scrollRect = GetComponent<VIPScrollRect>();
    }

    /// <summary>
    /// 定位到ScrollRect其中一个item（适用于搜索）
    /// </summary>
    /// <param name="item">需要定位到的目标</param>
    public void Location(Transform item)
    {
        Vector3 itemCurrentLocalPostion = scrollRect.GetComponent<RectTransform>().InverseTransformVector(ConvertLocalPosToWorldPos(item));
        Vector3 itemTargetLocalPos = scrollRect.GetComponent<RectTransform>().InverseTransformVector(ConvertLocalPosToWorldPos(viewport));
        Vector3 diff = itemTargetLocalPos - itemCurrentLocalPostion;
        diff.z = 0.0f;
        var newNormalizedPosition = new Vector2(
            diff.x / (content.rect.width - viewport.rect.width),
            diff.y / (content.rect.height - viewport.rect.height)
            );
        newNormalizedPosition = scrollRect.normalizedPosition - newNormalizedPosition;
        newNormalizedPosition.x = Mathf.Clamp01(newNormalizedPosition.x);
        newNormalizedPosition.y = Mathf.Clamp01(newNormalizedPosition.y);
        DOTween.To(() => scrollRect.normalizedPosition, x => scrollRect.normalizedPosition = x, newNormalizedPosition, 0.8f);
    }

    private Vector3 ConvertLocalPosToWorldPos(Transform item,VIPPosition position = VIPPosition.UP)
    {
        RectTransform target = item as RectTransform;
        Vector3 pivotOffset = Vector3.zero;
        switch (position) {
            case VIPPosition.UP:
                {
                    //顶部
                    pivotOffset = new Vector3(
                        (1f - target.pivot.x) * target.rect.size.x,
                        (1f - target.pivot.y) * target.rect.size.y,
                        0f);
                }
                break;
            case VIPPosition.CENTER:
                {
                    //居中
                    pivotOffset = new Vector3(
                        (0.5f - target.pivot.x) * target.rect.size.x,
                        (0.5f - target.pivot.y) * target.rect.size.y,
                        0f);
                }
                break;
        }
        Vector3 localPosition = target.localPosition + pivotOffset;
        return target.parent.TransformPoint(localPosition);
    }

    /// <summary>
    /// 滑动完成的回调
    /// </summary>
    /// <param name="slideComplete"></param>
    public void SlideComplete(UnityAction<GameObject> slideComplete) {
        this.slideComplete = slideComplete;
    }

}
